package com.yami.shop.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.model.CategoryShop;
import com.yami.shop.bean.model.ChannelUserRelationRecord;

import com.yami.shop.bean.model.User;
import com.yami.shop.bean.model.UserImg;
import com.yami.shop.bean.vo.PersonNft;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.DataWebService;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.common.util.StringUtils;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.dao.ChannelUserRelationRecordMapper;
import com.yami.shop.service.AttachFileService;
import com.yami.shop.service.ChannelUserRelationRecordService;
import com.yami.shop.service.UserImgService;
import com.yami.shop.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
public class ChannelUserRelationRecordServiceImpl extends ServiceImpl<ChannelUserRelationRecordMapper, ChannelUserRelationRecord> implements ChannelUserRelationRecordService {

    private static final Logger logger = LoggerFactory.getLogger(ChannelUserRelationRecordServiceImpl.class);

    @Autowired
    private ChannelUserRelationRecordMapper channelUserRelationRecordMapper;
    @Autowired
    private DataWebService dataWebService;
    @Autowired
    private ShopConfig shopConfig;
    @Autowired
    private UserService userService;
    @Autowired
    private UserImgService userImgService;
    @Autowired
    private AttachFileService attachFileService;
    @Override
    public ChannelUserRelationRecord getChannelAddressByaddress(String address, String chainCode) {
        return channelUserRelationRecordMapper.getChannelAddressByaddress(address, chainCode);
    }

    @Override
    public ChannelUserRelationRecord getinfoByUserIdChainCodeChannelCode(String userId, String chainCode, String channelCode, String type) {
        return channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode,channelCode,type);
    }

    @Override
    public ChannelUserRelationRecord getUserByChannelUserId(String channelUserId, String chainCode, String channelCode) {
        return channelUserRelationRecordMapper.getUserByChannelUserId(channelUserId,chainCode,channelCode);
    }


    @Override
    public List<Map<String, Object>> getHomeChannelList(String userId) {
        return channelUserRelationRecordMapper.getHomeChannelList(userId);
    }

    @Override
    public List<Map<String, Object>> getCreateUserChainChannelList(String userId) {
        User userByUserId = userService.getUserByUserId(userId);
        if(StrUtil.isBlank(userByUserId.getIdNumber())){
            throw new YamiShopBindException("请先实名");
        }
        Boolean bigMan = userService.isBigMan(userByUserId.getIdNumber());
        List<Map<String, Object>> createUserChainChannelList = channelUserRelationRecordMapper.getCreateUserChainChannelList(userId, null, null,bigMan);
        createUserChainChannelList.forEach(record -> {
            if (Integer.valueOf(record.get("num").toString()) == 1) {
                record.put("remark", "平台");
            } else if (Integer.valueOf(record.get("num").toString()) == 2) {
                record.put("remark", "发行");
            } else {
                record.put("remark", "平台/发行");
            }
        });
        return createUserChainChannelList;
    }

    @Override
    public List<Map<String, Object>> getUserHasChannelList(String userId, String chainCode) {
        List<Map<String, Object>> userHasChannelList = channelUserRelationRecordMapper.getUserHasChannelList(userId, chainCode);
        return userHasChannelList;
    }

    @Override
    public List<Map<String, Object>> getHomeChainList(String userId, String channelCode) {
        return channelUserRelationRecordMapper.getHomeChainList(userId, channelCode);
    }

    @Override
    public List<Map<String, Object>> userBlockchain(String userId) {
        return channelUserRelationRecordMapper.userBlockchain(userId);
    }

    @Override
    public List<Map<String, Object>> allChannelList(String chainCode) {
        return channelUserRelationRecordMapper.allChannelList(chainCode);
    }

    @Override
    public Boolean isHasDTCAddress(String userId, String chainCode, String channelCode) {
        ChannelUserRelationRecord record = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode,channelCode,"1");
        if (Objects.isNull(record)) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Boolean isHasAllAddress(String userId, String chainCode, String channelCode, String type) {
        ChannelUserRelationRecord record = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode,channelCode,type);
        if (Objects.isNull(record)) {
            return false;
        } else {
            return true;
        }
    }
    @Override
    public void removeAddress(String userId, String chainCode, String channelCode) {
        channelUserRelationRecordMapper.removeAddress(userId, chainCode,channelCode);
    }
    @Override
    @Transactional
    public void createDtcAddress(String userId, String chainCode, String channelCode) {
        ChannelUserRelationRecord res = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode,channelCode,"1");
        if (res == null) {
            ChannelUserRelationRecord one = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode,null,"1");
            if(Objects.isNull(one)){
                User user = userService.getUserByUserId(userId);
                if (StrUtil.isEmpty(user.getIdNumber())) {
                    throw new YamiShopBindException("yami.dtc.user.check.realname");
                }
                Map<String, String> obj = new HashMap<>();
                obj.put("chainCode", chainCode);
                obj.put("idNumber", user.getIdNumber());
                obj.put("mobile", user.getUserMobile());
                String url = shopConfig.getApiGatewayUrl() + "/nft/outapi/api/nftmint/generate?";
                JSONObject jsonObject = dataWebService.hutoolGetWebService(url, obj,null,null);
                if(jsonObject.getInteger("code")!= Constant.SUCCESS_CODE){
                    logger.info("获取{}",jsonObject.getString("msg"));
                    throw new MailException(jsonObject.getString("msg"));
                }
                JSONObject resObj = jsonObject.getJSONObject("data");
                String mnemonic = resObj.getString("mnemonic");
                String address = resObj.getString("address");
                ChannelUserRelationRecord record = new ChannelUserRelationRecord().builder().userId(userId).channelUserId(userId).channelCode(channelCode).chainCode(chainCode).address(address).mnemonic(mnemonic).status(0).createTime(new Date()).lastTime(new Date()).type("1").build();
                channelUserRelationRecordMapper.insert(record);
            }else{
                ChannelUserRelationRecord record = new ChannelUserRelationRecord().builder().userId(userId).channelUserId(userId).channelCode(channelCode).chainCode(chainCode).address(one.getAddress()).mnemonic(one.getMnemonic()).status(0).createTime(new Date()).lastTime(new Date()).type("1").build();
                channelUserRelationRecordMapper.insert(record);
            }
        }
    }

    @Override
    public ChannelUserRelationRecord exportChannelAddress(String userId, String chainCode, String channelCode) {
        User userByUserId = userService.getUserByUserId(userId);
        if (StrUtil.isEmpty(userByUserId.getIdNumber())) {
            throw new YamiShopBindException("yami.dtc.user.check.realname");
        }
        ChannelUserRelationRecord channelUserRelationRecord = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode, channelCode,"2");
        if (channelUserRelationRecord != null) {
            throw new YamiShopBindException("yami.channel.ischeck");
        }
        Map<String, String> obj = new HashMap<>();
        obj.put("channelCode", channelCode);
        obj.put("chainCode", chainCode);
        obj.put("name", userByUserId.getRealName());
        obj.put("callPhone", userByUserId.getUserMobile());
        obj.put("idNumber", userByUserId.getIdNumber());
        String url = shopConfig.getApiGatewayUrl() + "/personnft/outapi/app/user/registerAndAuthentication";
        JSONObject jsonObject = dataWebService.hutoolPostWebService(url, obj,null,null);
        if (null == jsonObject || jsonObject.getInteger("code") != Constant.SUCCESS_CODE ) {
            logger.info("{}",jsonObject.getString("msg"));
            throw new YamiShopBindException( jsonObject.getString("msg"));
        }
        JSONObject data = jsonObject.getJSONObject("data");
        List<ChannelUserRelationRecord> address = channelUserRelationRecordMapper.selectList(Wrappers.lambdaQuery(ChannelUserRelationRecord.class).eq(ChannelUserRelationRecord::getAddress, data.getString("address")).eq(ChannelUserRelationRecord::getStatus, 0).eq(ChannelUserRelationRecord::getChainCode, chainCode));
        if(address.size()>0){
            User userByUserId1 = userService.getUserByUserId(address.get(0).getUserId());
            throw new YamiShopBindException("该钱包地址已经在号码"+userByUserId1.getUserMobile()+"用户中创建");
        }
        ChannelUserRelationRecord record = new ChannelUserRelationRecord().builder().channelUserId(data.getString("userId")).userId(userId).channelCode(channelCode).chainCode(chainCode).address(data.getString("address")).mnemonic(data.getString("mnemonic")).status(0).createTime(new Date()).lastTime(new Date()).type("2").build();
        channelUserRelationRecordMapper.insert(record);
        return record;
    }

    public void createUserAllChannel(String userId, String chainCode, String channelCode) {
        User userByUserId = userService.getUserByUserId(userId);
        if (StrUtil.isEmpty(userByUserId.getIdNumber())) {
            throw new YamiShopBindException("yami.dtc.user.check.realname");
        }
        createDtcAddress(userId, chainCode, channelCode);
        exportChannelAddress(userId, chainCode, channelCode);
    }


    @Override
    @Transactional
    public void createUserChannel(String userId, String chainCode, String channelCode) {
        ChannelUserRelationRecord lastChannel = channelUserRelationRecordMapper.getLastChannel(userId);
        if (Objects.isNull(lastChannel)) {
            // 设置标记位
            RedisUtil.set("POSITIONGUIDANCEEXPORT::" + userId, userId, 0);
        }
        List<Map<String, Object>> createUserChannelList = channelUserRelationRecordMapper.getCreateUserChainChannelList(userId, chainCode, channelCode,null);
        Integer num = 0;
        // case when sum(num) = 3 then '' when  sum(num) = 2 then '微发行' when sum(num) = 1 then '平台' end as remark
        if (createUserChannelList.size() != 1) {
            List<ChannelUserRelationRecord> userAllAddress = channelUserRelationRecordMapper.getUserAllAddress(userId, chainCode, channelCode);
            if(userAllAddress.size()>0){
                throw new YamiShopBindException("该钱包已经创建");
            }else{
                throw new YamiShopBindException("平台签约链失效，请联系该平台");
            }
        }
        num = Integer.valueOf(createUserChannelList.get(0).get("num").toString());
        if (num == 1) {
            // 创建平台
            logger.debug("userId={}添加平台钱包", userId);
            exportChannelAddress(userId, chainCode, channelCode);
        } else if (num == 2) {
            // 创建微发行
            logger.debug("userId={}添加微发行钱包", userId);
            createDtcAddress(userId, chainCode, channelCode);
        } else {
            // 都创建
            logger.debug("userId={}添加两个钱包", userId);
            createUserAllChannel(userId, chainCode, channelCode);
        }
    }

    @Override
    public List<ChannelUserRelationRecord> getUserAllAddress(String userId, String chainCode, String channelCode,Long isRed) {
        List<ChannelUserRelationRecord> userAllAddress = channelUserRelationRecordMapper.getUserAllAddress(userId, chainCode, channelCode);
        Iterator<ChannelUserRelationRecord> it = userAllAddress.iterator();
        while (it.hasNext()) {
            ChannelUserRelationRecord record = it.next();
            if (record.getType().equals("1")) {
                // 获取微发行藏品数量
                PersonNft personNft = PersonNft.builder().userId(userId).channelCode(channelCode).chainCode(chainCode).isRed(isRed).build();
                Integer integer = channelUserRelationRecordMapper.getUserHoldNftCount(personNft);
                record.setTokenCount(integer);
                if (integer == 0) {
                    it.remove();
                }
            }else{
                // 获取微发行藏品数量
//                Map<String, String> stringObjectMap = new HashMap<>();
//                stringObjectMap.put("userId", record.getChannelUserId());
//                stringObjectMap.put("channelCode", channelCode);
//                stringObjectMap.put("chainCode", chainCode);
//                String url = shopConfig.getApiGatewayUrl() + "/personnft/outapi/app/personnft/getAllcount?";
//                JSONObject jsonObject = dataWebService.hutoolGetWebService(url, stringObjectMap,null,null);
//                if(jsonObject.getInteger("code")== Constant.SUCCESS_CODE){
//                    record.setTokenCount(jsonObject.getInteger("data"));
//                }
            }
        }
        return userAllAddress;
    }

    @Override
    public Map<String, Object> getUserOneAddress(String userId, String type) {
        Map<String, Object> map = new HashMap<>();
        String codeAndUserId = RedisUtil.get("channelCode::" + userId);
        String[] userArr = codeAndUserId.split(":");
        Map<String, Object> channelInfo = channelUserRelationRecordMapper.getChannelInfoByCode(userArr[0]);
        Map<String, Object> chainInfo = channelUserRelationRecordMapper.getChainInfoByCode(userArr[2]);
        //随机type
        ChannelUserRelationRecord userAllAddress = null;
        if(StrUtil.isEmpty(type)){
            List<ChannelUserRelationRecord> allAddress = channelUserRelationRecordMapper.getUserAllAddress(userId, userArr[2], userArr[0]);
            userAllAddress = allAddress.get(0);
        }else{
            userAllAddress = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, userArr[2], userArr[0], type);
        }
        map.put("channelUserInfo", channelInfo);
        map.put("nftPlatform", chainInfo);
        map.put("channelAddress", userAllAddress);
        RedisUtil.set("channelCode::" + userId, userArr[0] + ":" + userAllAddress.getChannelUserId() + ":" + userArr[2] + ":" + type, 0);
        userAllAddress.setTimes(userAllAddress.getTimes()+1);
        userAllAddress.setLastTime(new Date());
        channelUserRelationRecordMapper.updateById(userAllAddress);
//        if(!userArr[3].equals(type)){
//            deleteTreeImg(userId);
//        }
        return map;
    }

    @Override
    public Map<String, Object> getChannelInfo(String userId, String chainCode, String channelCode, String typeParm) {
//        if(StringUtils.isNotEmpty(channelCode) || StringUtils.isNotEmpty(chainCode)){
//            deleteTreeImg(userId);
//        }
        Map<String, Object> map = new HashMap<>();
        String channelUserId = userId;
        ChannelUserRelationRecord lastChannel = null;
        Integer size = 1;
        if (StringUtils.isEmpty(channelCode)) {
            lastChannel = channelUserRelationRecordMapper.getLastChannel(userId);
            channelCode = lastChannel.getChannelCode();
            chainCode = lastChannel.getChainCode();

        } else if (StringUtils.isEmpty(chainCode)) {
            List<ChannelUserRelationRecord> homeChainRecordList = channelUserRelationRecordMapper.getHomeChainRecordList(userId, channelCode);
            if (homeChainRecordList.size() == 0) {
                throw new YamiShopBindException("yami.sys.illegalArgument");
            }
            chainCode = homeChainRecordList.get(0).getChainCode();
            lastChannel = homeChainRecordList.get(0);
        } else {

            if(StrUtil.isEmpty(typeParm)){
                List<ChannelUserRelationRecord> allAddress = channelUserRelationRecordMapper.getUserAllAddress(userId, chainCode, channelCode);
                lastChannel = allAddress.get(0);
            }else{
                lastChannel = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(userId, chainCode, channelCode,typeParm);
            }
        }

        Map<String, Object> channelInfo = channelUserRelationRecordMapper.getChannelInfoByCode(channelCode);
        Map<String, Object> chainInfo = channelUserRelationRecordMapper.getChainInfoByCode(chainCode);
        map.put("channelUserInfo", channelInfo);
        map.put("nftPlatform", chainInfo);

        List<ChannelUserRelationRecord> userAllAddress = channelUserRelationRecordMapper.getUserAllAddress(userId, chainCode, channelCode);
        if (userAllAddress.size() > 1) {
            PersonNft personNft = PersonNft.builder().userId(userId).channelCode(channelCode).chainCode(chainCode).build();
            Integer count = channelUserRelationRecordMapper.getUserHoldNftCount(personNft);
            size = count>0 ? 2 :1;
            if("1".equals(lastChannel.getType())&& count ==0 ){
                lastChannel = "2".equals(userAllAddress.get(0).getType()) ? userAllAddress.get(0) : userAllAddress.get(1);
            }
        }
        map.put("channelAddress", lastChannel);
        map.put("addressCount", size);
        RedisUtil.set("channelCode::" + userId, lastChannel.getChannelCode() + ":" + lastChannel.getChannelUserId() + ":" + lastChannel.getChainCode() + ":" + lastChannel.getType(), 0);
        // 添加次数
        lastChannel.setTimes(lastChannel.getTimes() + 1);
        lastChannel.setLastTime(new Date());
        channelUserRelationRecordMapper.updateById(lastChannel);
        // 返回用户渠道对象
        return map;
    }

    private void deleteTreeImg(String userId){
        try {
            UserImg one = userImgService.getOne(new QueryWrapper<UserImg>().eq("user_id", userId).eq("type", 1));
            // 没有生成图片数据
            if(ObjectUtil.isNotEmpty(one)){
                if("1".equals(one.getStatus())){
                    attachFileService.deleteFile(one.getSourceUrl());
                }
                userImgService.removeById(one);
            }
        }catch (Exception e){
            log.error("清除生涯树缓存图片异常:"+e.getMessage());
        }

    }


    @Override
    public Map<String, Object> getUserByCallPhone(String userId, String callPhone) {
        String codeAndUserId = RedisUtil.get("channelCode::" + userId);
        String[] userArr = codeAndUserId.split(":");
        Map<String, Object> map = new HashMap<>();
        if ("1".equals(userArr[3])) {
            User user = userService.getUserDetailByCallPhone(callPhone);
            if (Objects.isNull(user)) {
                throw new YamiShopBindException("yami.phone.number.not.exists");
            }
            ChannelUserRelationRecord channelAddressByChainCode = channelUserRelationRecordMapper.getinfoByUserIdChainCodeChannelCode(user.getUserId(),userArr[2],userArr[0], userArr[3]);
            if (Objects.isNull(channelAddressByChainCode)) {
                throw new YamiShopBindException("该用户没有创建该链钱包");
            }
            map.put("realName", user.getRealName());
            map.put("address", channelAddressByChainCode.getAddress());
            map.put("userId", user.getUserId());
        } else {
            String url = shopConfig.getApiGatewayUrl() + "/personnft/outapi/app/user/getOutInfoAll?";
            Map<String, String> param = new HashMap<>();
            param.put("channelCode", userArr[0]);
            param.put("chainCode", userArr[2]);
            param.put("callPhone", callPhone);
            JSONObject jsonObject = dataWebService.hutoolGetWebService(url, param,null,null);
            if(jsonObject.getInteger("code")== Constant.WARN){
                logger.info("获取{}",jsonObject.getString("msg"));
                throw new MailException(jsonObject.getString("msg"));
            }
            if(jsonObject.getInteger("code")!= Constant.SUCCESS_CODE){
                logger.info("获取{}",jsonObject.getString("msg"));
                throw new YamiShopBindException(jsonObject.getString("msg"));
            }
            JSONObject user = jsonObject.getJSONObject("data");
            if (user == null) {
                throw new YamiShopBindException("yami.phone.number.not.exists");
            }
            // 返回用户渠道对象
            map.put("realName", user.getString("realName"));
            map.put("address", user.getString("address"));
            map.put("userId", user.getString("userId"));
        }
        return map;
    }


}
